#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h> 
#include <stdlib.h>       
#include <string.h>
#include <pthread.h>
//#include <sys/sem.h>
#include <errno.h>
#include <sys/ipc.h>
//#include <sys/msg.h>
#include <sys/timeb.h>
#include <sys/socket.h>
//#include <sys/socketvar.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <semaphore.h>
#include <string.h>
#include <termios.h>
#include <linux/input.h>
#include <semaphore.h>
#include <linux/shm.h>
#include <asm/unistd.h>
#include <sys/poll.h>
#include <sys/statfs.h>

#include "../common.h"

static const unsigned int cpuUsagePercentSleepTime = 5;	//second
static const char internalSdMountPoint[] = "/mnt/internal_sd";
static const char externalSdMountPoint[] = "/mnt/external_sd";
static const char usbStorageMountPoint[] = "/mnt/usb_storage";

int getCpuUsagePercent(unsigned char &cpuUsagePercent)
{
		CpuOccupy cpuStatus1;
		CpuOccupy cpuStatus2;
		int ret;
		
		ret = getCpuOccupyInfo(&cpuStatus1);
		if(ret < 0) return -1;
		
		sleep(cpuUsagePercentSleepTime);
		
		ret = getCpuOccupyInfo(&cpuStatus2);
		if(ret < 0) return -2;
	
		ret = calcCpuOccupyPercent(&cpuStatus1, &cpuStatus2, cpuUsagePercent);
		if(ret < 0) return -3;
			
		return 0;
}

static int getCpuOccupyInfo(CpuOccupy *cpuStatus)
{
		FILE *fp;
		int n;
		char buff[256];
		char logBuf[80];
		
		fp = fopen("/proc/stat", "r");
		if (fp == NULL)
		{
				writeLog("fopen /proc/stat fail !\n", __FILE__, __LINE__);
				return -1;
		}
		
		
		char *getRet = fgets(buff, sizeof(buff), fp);
		if(getRet == NULL)
		{
				writeLog("fgets fail !\n", __FILE__, __LINE__);
				return -2;	
		}
		
		int ret = sscanf(buff, "%s %u %u %u %u %u %u %u", cpuStatus->name,&cpuStatus->user,&cpuStatus->nice,&cpuStatus->system,&cpuStatus->idle, &cpuStatus->ioWait,&cpuStatus->irq,&cpuStatus->softIrq);
		if(ret < 0)
		{
				writeLog("sscanf fail ! \n", __FILE__, __LINE__);
				return -3;			
		}
		
		fclose(fp);
		return 0;
}

static int calcCpuOccupyPercent(CpuOccupy *c1, CpuOccupy *c2, unsigned char &cpuUsagePercent)
{
		unsigned int all1 = c1->user+c1->nice+c1->system+c1->idle+c1->ioWait+c1->irq+c1->softIrq;
		unsigned int all2 = c2->user+c2->nice+c2->system+c2->idle+c2->ioWait+c2->irq+c2->softIrq;
		unsigned int idle1 = c1->idle;
		unsigned int idle2 = c2->idle;
		char logBuf[80];
		
		if(all2 == all1)
		{
				sprintf(logBuf, "all2 == all1 ! all2 = %u\n", all2);
				writeLog(logBuf, __FILE__, __LINE__);
				return -1;	
		}
		
		int totalDiff = all2 - all1;
		int idleDiff = idle2 - idle1;
		if((totalDiff > 0 && idleDiff < 0) || (totalDiff < 0 && idleDiff > 0) || idleDiff > totalDiff)
		{
				sprintf(logBuf, "totalDiff idleDiff error ! all1,all2,idle1,idle2=%u,%u,%u,%u\n", all1,all2,idle1,idle2);
				writeLog(logBuf, __FILE__, __LINE__);
				return -2;	
		}
		
		unsigned int total = (unsigned int)abs(totalDiff);
		unsigned int idle = (unsigned int)abs(idleDiff);
		if(idle > total)
		{
				sprintf(logBuf, "idle > total ! total,idle = %u,%u\n", total,idle);
				writeLog(logBuf, __FILE__, __LINE__);
				return -3;	
		}
		
		//printf("total,idle = %d,%d\n", total,idle);
		
		//unsigned int use = total - idle;
		//unsigned int use2 = use * 100;
		//unsigned int percent1 = use2 / total;
		//unsigned char tmpCpuUsagePercent = (unsigned char)(percent1 & 0x000000FF);
		
		cpuUsagePercent = (unsigned char)(((total - idle) * 100 / total) & 0x000000FF);
		//printf("cpuUsagePercent = %x\n", cpuUsagePercent);
		return 0;
}


int getMemoryOccupy(unsigned long long &total, unsigned long long &use) //Byte
{
		FILE *fp;
		int n;
		char buff[256];
		MemoryOccupy info;
		
		fp = fopen("/proc/meminfo", "r");
		if(fp == NULL)
		{
				writeLog("fopen /poc/meminfo fail !\n", __FILE__, __LINE__);
				return -1;	
		}

		fgets(buff, sizeof(buff), fp);
		sscanf(buff, "%s %llu %s", info.totalName, &info.total, info.totalUnit);

		fgets(buff, sizeof(buff), fp);
		sscanf(buff, "%s %llu %s", info.freeName, &info.free, info.freeUnit);

		//printf("total,free=%llu,%llu\n", info.total,info.free);
		//printf("totalName,totalUnit,freeName,freeUnit=%s,%s,%s,%s\n", info.totalName,info.totalUnit,info.freeName,info.freeUnit);
		if(info.total < info.free)
		{
				char logBuf[80];
				sprintf(logBuf, "info.total < info.free ! total,free=%llu,%llu\n", info.total,info.free);
				return -2;
		}

		unsigned long long useTmp = (info.total - info.free) * 1024;
		unsigned long long totalTemp = info.total * 1024;
		//printf("getMemoryOccupy: totalTemp,useTmp = %llu,%llu\n", totalTemp,useTmp);
		//printf("&total,&use=%u,%u\n", &total,&use);
		//printf("getMemoryOccupy: before total,use = %llu,%llu\n", total,use);
		total = totalTemp;
		use = useTmp;
		//printf("getMemoryOccupy: after total,use = %llu,%llu\n", total,use);
		fclose(fp);
		return 0;
}


int getInternalSdInfo(unsigned long long &totalBytes, unsigned long long &useBytes)
{
		return getStorageInfo(internalSdMountPoint, totalBytes, useBytes);
}

int getExternalSdInfo(unsigned long long &totalBytes, unsigned long long &useBytes)
{
		return getStorageInfo(externalSdMountPoint, totalBytes, useBytes);
}

int getStorageInfo(const char *mountPoint, unsigned long long &totalBytes, unsigned long long &useBytes)
{
		//printf("into getStorageInfo ! mountPoint = %s\n", mountPoint);
		char logBuf[80];
		int ret;
		struct statfs info;
		unsigned long long freeBytes;
		
		if(mountPoint == NULL)
		{
				writeLog("mountPoint == NULL\n", __FILE__, __LINE__);	
				return -1;
		}

		ret = statfs(mountPoint, &info);
		if(ret < 0)
		{
				sprintf(logBuf, "statfs fail ! mountPoint = %s\n", mountPoint);
				writeLog(logBuf, __FILE__, __LINE__);	
				return -2;
		}

		//printf("%s:f_bsize,f_blocks,f_bfree,f_bavail = %lld,%lld,%lld,%lld\n", mountPoint,info.f_bsize,info.f_blocks,info.f_bfree,info.f_bavail);
		totalBytes = (unsigned long long)(info.f_bsize) * (unsigned long long)(info.f_blocks);
		freeBytes = (unsigned long long)(info.f_bsize) * (unsigned long long)(info.f_bfree);
		useBytes = totalBytes - freeBytes;

		//printf("%s: totalBytes=%llu, useBytes=%llu\n", mountPoint,totalBytes,useBytes);
		return 0;
}

int getStorageInfo(const char *mountPoint, unsigned long long &capacity, SpaceType spaceType)
{
		char logBuf[80];
		int ret;
	
		struct statfs info;
		unsigned long long totalBytes;
		unsigned long long freeBytes;
		unsigned long long useBytes;
		
		if(mountPoint == NULL)
		{
				writeLog("mountPoint == NULL\n", __FILE__, __LINE__);	
				return -1;
		}
		
		if(spaceType >= _maxSpaceType)
		{
				sprintf(logBuf, "spaceType >= _maxSpaceType ! spaceType=%u,_maxSpaceType=%u\n", spaceType,_maxSpaceType);	
				writeLog(logBuf, __FILE__, __LINE__);
				return -2;
		}
		
		ret = statfs(mountPoint, &info);
		if(ret < 0)
		{
				sprintf(logBuf, "statfs fail ! mountPoint = %s\n", mountPoint);
				writeLog(logBuf, __FILE__, __LINE__);	
				return -3;
		}
		
		totalBytes = (unsigned long long)(info.f_bsize * info.f_blocks);
		freeBytes = (unsigned long long)(info.f_bsize * info.f_bfree);
		useBytes = totalBytes - freeBytes;
		
		switch(spaceType)
		{
				case _totalSpaceKB:
					capacity = totalBytes / 1024;
					break;
				case _totalSpaceB:
					capacity = totalBytes;
					break;
				case _freeSpaceKB:
					capacity = freeBytes / 1024;
					break;
				case _freeSpaceB:
					capacity = freeBytes;
					break;
				case _useSpaceKB:
					capacity = useBytes / 1024;
					break;
				case _useSpaceB:
					capacity = useBytes;
					break;
				default:
					sprintf(logBuf, "unknow error ! spaceType = %u\n", spaceType);
					writeLog(logBuf, __FILE__, __LINE__);	
					return -4;
					break;
		}
		
		return 0;
}


int checkUsbStorage(unsigned char &has)
{
		int ret;

		struct statfs info;
		unsigned long long totalBytes;
		unsigned long long freeBytes;
		unsigned long long useBytes;
	
		ret = statfs(usbStorageMountPoint, &info);
		if(ret < 0)
		{
				has = 0;
				writeLog("checkUsbStorage: statfs fail !\n", __FILE__, __LINE__);
				return 0;
		}
		
		if(info.f_blocks <= 0)
		{
				has = 0;
				char logBuf[128];
				sprintf(logBuf, "checkUsbStorage: info.f_blocks <= 0 ! info.f_blocks = %lld\n", info.f_blocks);
				writeLog(logBuf, __FILE__, __LINE__);
				return 0;	
		}
		
		has = 1;
		return 0;
}